﻿// Decompiled with JetBrains decompiler
// Type: Netick.Unity.NetickUnityUtils
// Assembly: Netick.Unity, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null
// MVID: E128C7FD-39ED-4452-86AC-6EC748457030
// Assembly location: D:\WorkSpaceDemo\UPM\NetickForUnity\Netick\Runtime\Netick.Unity.dll
// XML documentation location: D:\WorkSpaceDemo\UPM\NetickForUnity\Netick\Runtime\Netick.Unity.xml

using System;
using System.Numerics;
using System.Runtime.CompilerServices;
using UnityEngine;

#nullable disable
namespace Netick.Unity;

public static class NetickUnityUtils
{
  internal const float QuatMemberPrecisionInverse = 256f;
  internal const float QuatMemberPrecision = 0.00392156839f;

  public static unsafe Angle GetSmoothAngle(
    NetickEngine engine,
    int* data,
    ref Interpolator interpolator,
    InterpolationSource interpolationSource)
  {
    int* from;
    int* to;
    float alpha;
    return !engine.IsInvokingNetworkRender || !interpolator.GetInterpolationDataPtr(interpolationSource, out from, out to, out alpha) ? Angle.CreateAngle(data) : (Angle) Mathf.LerpAngle((float) Angle.CreateAngle(from), (float) Angle.CreateAngle(to), alpha);
  }

  public static unsafe NetworkBool GetSmoothNetworkBool(
    NetickEngine engine,
    int* data,
    ref Interpolator interpolator,
    InterpolationSource interpolationSource)
  {
    if (!engine.IsInvokingNetworkRender)
      return (NetworkBool) (*data == 1);
    int* from;
    int* to;
    float alpha;
    return interpolator.GetInterpolationDataPtr(interpolationSource, out from, out to, out alpha) ? (NetworkBool) (*((double) alpha < 0.5 ? from : to) == 1) : (NetworkBool) (*data == 1);
  }

  public static unsafe bool GetSmoothBool(
    NetickEngine engine,
    int* data,
    ref Interpolator interpolator,
    InterpolationSource interpolationSource)
  {
    if (!engine.IsInvokingNetworkRender)
      return (bool) *(byte*) data;
    int* from;
    int* to;
    float alpha;
    return interpolator.GetInterpolationDataPtr(interpolationSource, out from, out to, out alpha) ? (bool) *((double) alpha < 0.5 ? (byte*) from : (byte*) to) : (bool) *(byte*) from;
  }

  public static unsafe int GetSmoothInt(
    NetickEngine engine,
    int* data,
    ref Interpolator interpolator,
    InterpolationSource interpolationSource)
  {
    int* from;
    int* to;
    float alpha;
    return !engine.IsInvokingNetworkRender || !interpolator.GetInterpolationDataPtr(interpolationSource, out from, out to, out alpha) ? *data : *((double) alpha < 0.5 ? from : to);
  }

  public static unsafe double GetSmoothDouble(
    NetickEngine engine,
    int* data,
    ref Interpolator interpolator,
    InterpolationSource interpolationSource)
  {
    int* from;
    int* to;
    float alpha;
    return !engine.IsInvokingNetworkRender || !interpolator.GetInterpolationDataPtr(interpolationSource, out from, out to, out alpha) ? (double) NetickUnityUtils.GetDouble(data) : NetickUnityUtils.DoubleLerp((double) NetickUnityUtils.GetDouble(from), (double) NetickUnityUtils.GetDouble(to), alpha);
  }

  public static unsafe float GetSmoothFloat(
    NetickEngine engine,
    int* data,
    ref Interpolator interpolator,
    InterpolationSource interpolationSource)
  {
    int* from;
    int* to;
    float alpha;
    return !engine.IsInvokingNetworkRender || !interpolator.GetInterpolationDataPtr(interpolationSource, out from, out to, out alpha) ? NetickUnityUtils.GetFloat(data, interpolator.Precision) : Mathf.Lerp(NetickUnityUtils.GetFloat(from, interpolator.Precision), NetickUnityUtils.GetFloat(to, interpolator.Precision), alpha);
  }

  public static unsafe Vector2 GetSmoothVector2(
    NetickEngine engine,
    int* data,
    ref Interpolator interpolator,
    InterpolationSource interpolationSource)
  {
    int* from;
    int* to;
    float alpha;
    return !engine.IsInvokingNetworkRender || !interpolator.GetInterpolationDataPtr(interpolationSource, out from, out to, out alpha) ? NetickUnityUtils.GetVector2(data, interpolator.Precision) : Vector2.Lerp(NetickUnityUtils.GetVector2(from, interpolator.Precision), NetickUnityUtils.GetVector2(to, interpolator.Precision), alpha);
  }

  public static unsafe Vector3 GetSmoothVector3(
    NetickEngine engine,
    int* data,
    ref Interpolator interpolator,
    InterpolationSource interpolationSource)
  {
    int* from;
    int* to;
    float alpha;
    return !engine.IsInvokingNetworkRender || !interpolator.GetInterpolationDataPtr(interpolationSource, out from, out to, out alpha) ? NetickUnityUtils.GetVector3(data, interpolator.Precision) : Vector3.Lerp(NetickUnityUtils.GetVector3(from, interpolator.Precision), NetickUnityUtils.GetVector3(to, interpolator.Precision), alpha);
  }

  public static unsafe Quaternion GetSmoothQuaternion(
    NetickEngine engine,
    int* data,
    ref Interpolator interpolator,
    InterpolationSource interpolationSource)
  {
    int* from;
    int* to;
    float alpha;
    return !engine.IsInvokingNetworkRender || !interpolator.GetInterpolationDataPtr(interpolationSource, out from, out to, out alpha) ? NetickUnityUtils.GetQuaternion(data, interpolator.Precision) : Quaternion.Slerp(NetickUnityUtils.GetQuaternion(from, interpolator.Precision), NetickUnityUtils.GetQuaternion(to, interpolator.Precision), alpha);
  }

  public static unsafe Color GetSmoothColor(
    NetickEngine engine,
    int* data,
    ref Interpolator interpolator,
    InterpolationSource interpolationSource)
  {
    int* from;
    int* to;
    float alpha;
    return !engine.IsInvokingNetworkRender || !interpolator.GetInterpolationDataPtr(interpolationSource, out from, out to, out alpha) ? NetickUnityUtils.GetColor(data, interpolator.Precision) : Color.Lerp(NetickUnityUtils.GetColor(from, interpolator.Precision), NetickUnityUtils.GetColor(to, interpolator.Precision), alpha);
  }

  [MethodImpl(MethodImplOptions.AggressiveInlining)]
  public static unsafe float GetFloat(int* data, float precision)
  {
    return (double) precision != -1.0 ? (float) *data * precision : *(float*) data;
  }

  [MethodImpl(MethodImplOptions.AggressiveInlining)]
  public static unsafe void SetFloat(int* data, float value, float precisionInverse)
  {
    if ((double) precisionInverse == -1.0)
      *(float*) data = value;
    else
      *data = (double) value > 0.0 ? (int) ((double) value * (double) precisionInverse + 0.5) : (int) ((double) value * (double) precisionInverse - 0.5);
  }

  [MethodImpl(MethodImplOptions.AggressiveInlining)]
  public static unsafe void SetColor(int* data, Color value, float precisionInverse)
  {
    if ((double) precisionInverse == -1.0)
    {
      *(float*) data = value.r;
      *(float*) (data + 1) = value.g;
      *(float*) (data + 2) = value.b;
      *(float*) (data + 3) = value.a;
    }
    else
    {
      *data = (double) value.r > 0.0 ? (int) ((double) value.r * (double) precisionInverse + 0.5) : (int) ((double) value.r * (double) precisionInverse - 0.5);
      data[1] = (double) value.g > 0.0 ? (int) ((double) value.g * (double) precisionInverse + 0.5) : (int) ((double) value.g * (double) precisionInverse - 0.5);
      data[2] = (double) value.b > 0.0 ? (int) ((double) value.b * (double) precisionInverse + 0.5) : (int) ((double) value.b * (double) precisionInverse - 0.5);
      data[3] = (double) value.a > 0.0 ? (int) ((double) value.a * (double) precisionInverse + 0.5) : (int) ((double) value.a * (double) precisionInverse - 0.5);
    }
  }

  [MethodImpl(MethodImplOptions.AggressiveInlining)]
  public static unsafe Color GetColor(int* data, float precision)
  {
    Color color = new Color();
    if ((double) precision == -1.0)
    {
      color.r = *(float*) data;
      color.g = *(float*) (data + 1);
      color.b = *(float*) (data + 2);
      color.a = *(float*) (data + 3);
    }
    else
    {
      color.r = (float) *data * precision;
      color.g = (float) data[1] * precision;
      color.b = (float) data[2] * precision;
      color.a = (float) data[3] * precision;
    }
    return color;
  }

  [MethodImpl(MethodImplOptions.AggressiveInlining)]
  public static unsafe Vector2 GetVector2(int* data, float precision)
  {
    Vector2 vector2 = new Vector2();
    if ((double) precision == -1.0)
    {
      vector2.x = *(float*) data;
      vector2.y = *(float*) (data + 1);
    }
    else
    {
      vector2.x = (float) *data * precision;
      vector2.y = (float) data[1] * precision;
    }
    return vector2;
  }

  [MethodImpl(MethodImplOptions.AggressiveInlining)]
  public static unsafe void SetVector2(int* data, Vector2 value, float precisionInverse)
  {
    if ((double) precisionInverse == -1.0)
    {
      *(float*) data = value.x;
      *(float*) (data + 1) = value.y;
    }
    else
    {
      *data = (double) value.x > 0.0 ? (int) ((double) value.x * (double) precisionInverse + 0.5) : (int) ((double) value.x * (double) precisionInverse - 0.5);
      data[1] = (double) value.y > 0.0 ? (int) ((double) value.y * (double) precisionInverse + 0.5) : (int) ((double) value.y * (double) precisionInverse - 0.5);
    }
  }

  [MethodImpl(MethodImplOptions.AggressiveInlining)]
  public static unsafe Vector3 GetVector3(int* data, float precision)
  {
    Vector3 vector3 = new Vector3();
    if ((double) precision == -1.0)
    {
      vector3.x = *(float*) data;
      vector3.y = *(float*) (data + 1);
      vector3.z = *(float*) (data + 2);
    }
    else
    {
      vector3.x = (float) *data * precision;
      vector3.y = (float) data[1] * precision;
      vector3.z = (float) data[2] * precision;
    }
    return vector3;
  }

  [MethodImpl(MethodImplOptions.AggressiveInlining)]
  public static unsafe void SetVector3(int* data, Vector3 value, float precisionInverse)
  {
    if ((double) precisionInverse == -1.0)
    {
      *(float*) data = value.x;
      *(float*) (data + 1) = value.y;
      *(float*) (data + 2) = value.z;
    }
    else
    {
      *data = (double) value.x > 0.0 ? (int) ((double) value.x * (double) precisionInverse + 0.5) : (int) ((double) value.x * (double) precisionInverse - 0.5);
      data[1] = (double) value.y > 0.0 ? (int) ((double) value.y * (double) precisionInverse + 0.5) : (int) ((double) value.y * (double) precisionInverse - 0.5);
      data[2] = (double) value.z > 0.0 ? (int) ((double) value.z * (double) precisionInverse + 0.5) : (int) ((double) value.z * (double) precisionInverse - 0.5);
    }
  }

  [MethodImpl(MethodImplOptions.AggressiveInlining)]
  public static unsafe void SetQuaternion(int* data, Quaternion value, float precisionInverse)
  {
    if ((double) precisionInverse == -1.0)
    {
      *(float*) data = value.x;
      *(float*) (data + 1) = value.y;
      *(float*) (data + 2) = value.z;
      *(float*) (data + 3) = value.w;
    }
    else
    {
      *data = (double) value.x > 0.0 ? (int) ((double) value.x * (double) precisionInverse + 0.5) : (int) ((double) value.x * (double) precisionInverse - 0.5);
      data[1] = (double) value.y > 0.0 ? (int) ((double) value.y * (double) precisionInverse + 0.5) : (int) ((double) value.y * (double) precisionInverse - 0.5);
      data[2] = (double) value.z > 0.0 ? (int) ((double) value.z * (double) precisionInverse + 0.5) : (int) ((double) value.z * (double) precisionInverse - 0.5);
      data[3] = (double) value.w > 0.0 ? (int) ((double) value.w * (double) precisionInverse + 0.5) : (int) ((double) value.w * (double) precisionInverse - 0.5);
    }
  }

  [MethodImpl(MethodImplOptions.AggressiveInlining)]
  public static unsafe Quaternion GetQuaternion(int* data, float precision)
  {
    Quaternion quaternion = new Quaternion();
    if ((double) precision == -1.0)
    {
      quaternion.x = *(float*) data;
      quaternion.y = *(float*) (data + 1);
      quaternion.z = *(float*) (data + 2);
      quaternion.w = *(float*) (data + 3);
    }
    else
    {
      quaternion.x = (float) *data * precision;
      quaternion.y = (float) data[1] * precision;
      quaternion.z = (float) data[2] * precision;
      quaternion.w = (float) data[3] * precision;
    }
    return quaternion;
  }

  [MethodImpl(MethodImplOptions.AggressiveInlining)]
  public static int QuatMemberPack(float value)
  {
    return (double) value <= 0.0 ? (int) ((double) value * 256.0 - 0.5) : (int) ((double) value * 256.0 + 0.5);
  }

  [MethodImpl(MethodImplOptions.AggressiveInlining)]
  public static float QuatMemberUnpack(int data) => (float) data * 0.00392156839f;

  [MethodImpl(MethodImplOptions.AggressiveInlining)]
  public static unsafe void SetQuaternionCompressed(int* data, Quaternion value)
  {
    int num1 = 0;
    float num2 = float.MinValue;
    float num3 = 1f;
    for (int index = 0; index < 4; ++index)
    {
      float num4 = 0.0f;
      if (index == 0)
        num4 = value.x;
      if (index == 1)
        num4 = value.y;
      if (index == 2)
        num4 = value.z;
      if (index == 3)
        num4 = value.w;
      float num5 = (double) num4 < 0.0 ? num4 * -1f : num4;
      if ((double) num5 > (double) num2)
      {
        num3 = (double) num4 < 0.0 ? -1f : 1f;
        num1 = index;
        num2 = num5;
      }
    }
    float num6;
    float num7;
    float num8;
    switch (num1)
    {
      case 0:
        num6 = value.y * num3;
        num7 = value.z * num3;
        num8 = value.w * num3;
        break;
      case 1:
        num6 = value.x * num3;
        num7 = value.z * num3;
        num8 = value.w * num3;
        break;
      case 2:
        num6 = value.x * num3;
        num7 = value.y * num3;
        num8 = value.w * num3;
        break;
      default:
        num6 = value.x * num3;
        num7 = value.y * num3;
        num8 = value.z * num3;
        break;
    }
    *data = num1;
    data[1] = NetickUnityUtils.QuatMemberPack(num6);
    data[2] = NetickUnityUtils.QuatMemberPack(num7);
    data[3] = NetickUnityUtils.QuatMemberPack(num8);
  }

  [MethodImpl(MethodImplOptions.AggressiveInlining)]
  public static unsafe Quaternion GetQuaternionCompressed(int* data)
  {
    int num1 = *data;
    float num2 = NetickUnityUtils.QuatMemberUnpack(data[1]);
    float num3 = NetickUnityUtils.QuatMemberUnpack(data[2]);
    float num4 = NetickUnityUtils.QuatMemberUnpack(data[3]);
    float num5 = Mathf.Sqrt((float) (1.0 - ((double) num2 * (double) num2 + (double) num3 * (double) num3 + (double) num4 * (double) num4)));
    switch (num1)
    {
      case 0:
        return new Quaternion()
        {
          x = num5,
          y = num2,
          z = num3,
          w = num4
        };
      case 1:
        return new Quaternion()
        {
          x = num2,
          y = num5,
          z = num3,
          w = num4
        };
      case 2:
        return new Quaternion()
        {
          x = num2,
          y = num3,
          z = num5,
          w = num4
        };
      case 3:
        return new Quaternion()
        {
          x = num2,
          y = num3,
          z = num4,
          w = num5
        };
      default:
        return new Quaternion();
    }
  }

  [MethodImpl(MethodImplOptions.AggressiveInlining)]
  public static unsafe float GetDouble(int* data) => *(float*) data;

  [MethodImpl(MethodImplOptions.AggressiveInlining)]
  internal static double DoubleLerp(double from, double to, float t)
  {
    return from + (to - from) * Math.Clamp((double) t, 0.0, 1.0);
  }

  public static void AddInterestBoxArea(this Netick.NetworkPlayer player, Bounds box, int layerIndex = 0)
  {
    player.AddInterestBoxArea(new NetickBounds(box.center.ToNumerics(), box.size.ToNumerics()), layerIndex);
  }

  public static float GetRemainingTime(
    this NetworkTimer timer,
    NetworkSandbox sandbox,
    bool usePredictedTiming = false)
  {
    return timer.GetRemainingTime(sandbox.Engine, usePredictedTiming);
  }

  public static float GetElapsedTime(
    this NetworkTimer timer,
    NetworkSandbox sandbox,
    bool usePredictedTiming = false)
  {
    return timer.GetElapsedTime(sandbox.Engine, usePredictedTiming);
  }

  public static bool IsStopped(
    this NetworkTimer timer,
    NetworkSandbox sandbox,
    bool usePredictedTiming = false)
  {
    return timer.IsStopped(sandbox.Engine, usePredictedTiming);
  }

  public static bool IsRunning(
    this NetworkTimer timer,
    NetworkSandbox sandbox,
    bool usePredictedTiming = false)
  {
    return timer.IsRunning(sandbox.Engine, usePredictedTiming);
  }

  [MethodImpl(MethodImplOptions.AggressiveInlining)]
  public static Vector3 ToNumerics(this Vector3 vec) => new Vector3(vec.x, vec.y, vec.z);

  [MethodImpl(MethodImplOptions.AggressiveInlining)]
  public static Quaternion ToNumerics(this Quaternion vec)
  {
    return new Quaternion(vec.x, vec.y, vec.z, vec.w);
  }

  [MethodImpl(MethodImplOptions.AggressiveInlining)]
  public static Vector3 FromNumerics(this Vector3 vec) => new Vector3(vec.X, vec.Y, vec.Z);

  [MethodImpl(MethodImplOptions.AggressiveInlining)]
  public static Quaternion FromNumerics(this Quaternion vec)
  {
    return new Quaternion(vec.X, vec.Y, vec.Z, vec.W);
  }

  [MethodImpl(MethodImplOptions.AggressiveInlining)]
  public static Bounds ToUnityBounds(this NetickBounds bounds)
  {
    return new Bounds(bounds.Center.FromNumerics(), bounds.Size.FromNumerics());
  }

  public static NetworkSandbox GetSandbox(this NetickEngine engine)
  {
    return engine.UserObject as NetworkSandbox;
  }

  public static void SetEnabled(this Component comp, NetworkSandbox sandbox, bool value)
  {
    if ((UnityEngine.Object) sandbox == (UnityEngine.Object) null)
    {
      if (comp is Renderer)
        ((Renderer) comp).enabled = value;
      else
        ((Behaviour) comp).enabled = value;
    }
    else
      sandbox.SetComponentEnabled(comp, value);
  }

  public static void NetworkPlayOneShot(
    this AudioSource audioSource,
    NetworkSandbox sandbox,
    AudioClip clip,
    float volumeScale = 1f)
  {
    if (!sandbox.IsVisible)
      return;
    audioSource.PlayOneShot(clip, volumeScale);
  }

  public static void NetworkPlay(this AudioSource audioSource, NetworkSandbox sandbox, ulong delay = 0)
  {
    if (!sandbox.IsVisible)
      return;
    audioSource.Play(delay);
  }

  public static void NetworkPlayScheduled(
    this AudioSource audioSource,
    NetworkSandbox sandbox,
    double time)
  {
    if (!sandbox.IsVisible)
      return;
    audioSource.PlayScheduled(time);
  }

  public static int RaycastAll(
    this PhysicsScene physics,
    Vector3 origin,
    Vector3 direction,
    RaycastHit[] hits,
    float maxDistance = float.PositiveInfinity,
    int layerMask = -5,
    QueryTriggerInteraction queryTriggerInteraction = QueryTriggerInteraction.UseGlobal)
  {
    return physics.Raycast(origin, direction, hits, maxDistance, layerMask, queryTriggerInteraction);
  }

  public static int RaycastAll(
    this PhysicsScene2D physics,
    Vector2 origin,
    Vector2 direction,
    float distance,
    ContactFilter2D contactFilter,
    RaycastHit2D[] results)
  {
    return physics.Raycast(origin, direction, distance, contactFilter, results);
  }
}
